package com.acme.bankapp.service.bank;

import com.acme.bankapp.domain.bank.*;
import com.acme.exceptions.*;

import java.io.File;
import java.io.IOException;

public class BankApplication {

	private static String serializationFile;
	private static String feedFile;
	private static BankService bankService;
	private static boolean serverMode = false;

	public static void main(String args[]) throws ClassNotFoundException,
			IOException, InvalidFeed {
		parseArgs(args);
		bankService = new BankService(new File(
				serializationFile != null ? serializationFile : "bank.bin"));
		Bank bank;
		if (feedFile != null) {
			bank = BankDataLoaderService.loadFeed(new File(feedFile));
		} else {
			if (serializationFile != null) {
				bank = bankService.readBank();
			} else {
				bank = bankService
						.createBank(new ClientRegistrationListener[] { new ClientRegistrationListener() { 
							public void onClientAdded(Client client) {
								System.out.println("Listener from outside: "
										+ client.getClientSalutation()
										+ "  registred");
							}
						} });
			}
		}
		if (serverMode) {
			BankServer server = new BankServer();
			server.startServer(bankService, bank);
		}

		addSampleClients(bank);
		bankService.printClients(bank);
		modifyBank(bank);
		System.out.println("Bank is modified");
		bankService.printClients(bank);
	}

	private static void parseArgs(String[] args) {
		int i = 0;
		while (i < args.length) {
			if (args[i].equals("-loadfeed")) {
				++i;
				if (i >= args.length) {
					throw new IllegalArgumentException();
				}
				feedFile = args[i];
			} else if (args[i].equals("-loadbank")) {
				++i;
				if (i >= args.length) {
					throw new IllegalArgumentException();
				}
				serializationFile = args[i];
			} else if (args[i].equals("-servermode")) {
				serverMode = true;
			} else {
				throw new IllegalArgumentException();
			}
			++i;
		}
	}

	private static void modifyBank(Bank bank) {
		for (Client cli : bankService.getClients(bank)) {
			if (Math.random() < 0.5) {
				cli.getAccount().deposit((int) (10000 * Math.random()));
			} else {
				try {
					cli.getAccount().withdraw((int) (10000 * Math.random()));
				} catch (OverDraftLimitExceededException e) {
					System.err.println("Error! " + cli.getClientSalutation()
							+ " is to greedy while using overdraft! Wanted="
							+ e.getAmountWanted() + ", MaxAllowed="
							+ e.getAmountAllowed() + " balance="
							+ e.getAccount().getBalance());
				} catch (NotEnoughFundsException e) {
					System.err.println("Error! " + cli.getClientSalutation()
							+ " is to greedy! Wanted=" + e.getAmountWanted());
				}
			}
		}
	}

	public static Client createSampleClient(String name, Gender gender) {
		Client client = new Client(name, gender);
		if (Math.random() < 0.5) {
			client.setAccount(new SavingsAccount((int) (Math.random() * 10000)));
		} else {
			client.setAccount(new CheckingAccount(
					(int) (Math.random() * 10000),
					(int) (Math.random() * 10000)));
		}
		return client;
	}

	public static void addSampleClients(Bank bank) {
		bankService.addClient(bank, createSampleClient("Mary", Gender.FEMALE));
		bankService.addClient(bank,
				createSampleClient("Johny Doe", Gender.MALE));
		bankService.addClient(bank,
				createSampleClient("Scrooge McDuck", Gender.MALE));
		bankService.addClient(bank, createSampleClient("Jimmy", Gender.MALE));
		bankService.addClient(bank, createSampleClient("Billy", Gender.MALE));
	}

}
